﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Text;

using System.IO;
using System.Xml.Serialization;
using System.Globalization;
using System.Threading;
using System.ComponentModel;
using Settings;


namespace AutoTrader
{
    public partial class AutoTraderForm
    {
        int         InitialLots = 1;
        int         Buy0Sell1 = 0;
        int         ClientNumber = 0;
        decimal     PipsStep = 0;
        decimal     SellPrice = 0;
        decimal     BuyPrice = 0;
        decimal     SellPrice2 = 0;
        decimal     BuyPrice2 = 0;
        bool        StopOrderTriggered;
        int         FailedCount;
        int         progressPosition;
        bool        bClosePosition;
        double      dResultAll=0;
        OrderInfo   BaseOrder = new OrderInfo();
        OrderInfo   StopOrder = new OrderInfo();

        private string GetOrderStatusName(int status)
        {
            string message = string.Empty;
            if (1 == status)
                message = "Requested";
            else if (2 == status)
                message = "Confirmed";
            else if (3 == status)
                message = "Executed";
            else if (4 == status)
                message = "Canceled";
            else if (5 == status)
                message = "Requested for Cancelling";
            else if( status < 0 )
                message = obj.GetErrDescription( status );
            else 
                message = "Unknown";

            return message;
        }

        // 25.10.2009 P.Peev
        private decimal GetTaxAmount()
        {
            decimal res = 0m;

            for( int i = InitialLots ; i <= BaseOrder.Lots ; i = i*2 )
                res = res + i * 0.20m;

            return ( res + res*0.2m );// 27.10.2009 P.Peev
        }

        private bool CheckPosition( ref double dCount, ref double dPrice, ref double dResult )
        {
            int errNumber = 0;
            try
            {
                obj.GetPosition( Settings.Settings.Instrument, ref dCount, ref dPrice, ref errNumber);
                if (errNumber < 0)
                {
                    myLogger.Add(string.Format("Error getting order status. {0}", obj.GetErrDescription(errNumber)));
                    return false;
                }

                dResult = obj.GetPositionRes( Settings.Settings.Instrument, Settings.Settings.Instrument.Remove(3), ref errNumber);
                if (errNumber < 0)
                {
                    myLogger.Add(string.Format("Error getting order result. {0}", obj.GetErrDescription(errNumber)));
                    return false;
                }
            }
            catch( Exception ex )
            {
                myLogger.Add( string.Format( "Runtime exception: {0}-{1}", ex.Message, ex.StackTrace ) );
                return false;
            }
            return true;
        }

        private void backgroundGetQuotes_DoWork(object sender, DoWorkEventArgs e)
        {
            string message = string.Empty;
            string format_string = string.Empty;
            double dBuyPrice=0, dSellPrice=0, dHiPrice=0, dLowPrice=0;
            double dPositionPrice=0, dPositionCount=0, dPositionResult=0;
            int errNumber = 0;

            BackgroundWorker worker = sender as BackgroundWorker;

            StopOrderTriggered = false;

///         main cicle
            try
            {
                //Create 
                myLogger.Add( "Job started." );
                errNumber = obj.CreateClientAPI( strExtNumber );

                if (errNumber >= 0)
                {
                    myLogger.Add( string.Format( "Cleint API Created for ExtNumber:{0}", strExtNumber ) );
                }
                else
                {
                    myLogger.Add(string.Format("CreateClientAPI fail. {0}", obj.GetErrDescription(errNumber)));
                    obj.DestroyClientAPI();
                    return;
                }

                if (!ReadOrderSettings())
                    return;

                if (!ReadCoursesSettings())
                    return;

                do
                {
                    if ((worker.CancellationPending == true))
                    {
                        e.Cancel = true;
                        break;
                    }
                    else
                    {
                        //GetQuote
                        Thread.Sleep(100);

                        BuyPrice2 = BuyPrice;
                        SellPrice2 = SellPrice;

                        obj.GetQuote(Settings.Settings.Instrument, ref dBuyPrice, ref dSellPrice, ref dHiPrice, ref dLowPrice, ref errNumber);
                        if (errNumber < 0)
                        {
                            myLogger.Add(string.Format("GetQuote fail. {0}", obj.GetErrDescription(errNumber)));
                            break;
                        }
                        BuyPrice = Convert.ToDecimal(dBuyPrice);
                        SellPrice = Convert.ToDecimal(dSellPrice);

                        if (progressPosition < 0) progressPosition = 0;
                        if (progressPosition > 100) progressPosition = 100;

                        worker.ReportProgress( progressPosition );

                        dResultAll = obj.GetTotalResult(Settings.Settings.Instrument.Substring(4, 3), ref errNumber);
                        if (errNumber < 0)
                        {
                            myLogger.Add(string.Format("Get Total Result Error.{0}", obj.GetErrDescription(errNumber)));
                        }

                        if( 0 == BaseOrder.ID )//if 0 there is no order - create one but first get two steps to decide buy or sell
                        {
                            if( !OpenOrders() )
                            {
                                myLogger.Add(string.Format("OpenOrders fail. " ));
                                break;
                            }
                        }

                        worker.ReportProgress(progressPosition);

                        if( !CheckPosition( ref dPositionCount, ref dPositionPrice, ref dPositionResult ) ) // check to position - if exists OK...if not cancel Stop order and create new
                        {
                            myLogger.Add(string.Format("CheckPosition fail. " ));
                            break;
                        }

                        // 02.11.2009 P.Peev
                        obj.GetQuote( Settings.Settings.Instrument, ref dBuyPrice, ref dSellPrice, ref dHiPrice, ref dLowPrice, ref errNumber);
                        if (errNumber < 0)
                        {
                            myLogger.Add(string.Format("GetQuote fail. {0}", obj.GetErrDescription(errNumber)));
                            break;
                        }
                        BuyPrice = Convert.ToDecimal(dBuyPrice);
                        SellPrice = Convert.ToDecimal(dSellPrice);

                        if (dPositionCount == 0)// there is no open position
                        {                                                        
                            myLogger.Add( string.Format("POSITION not found!!" ) );
                            StopOrderTriggered = true;
                            FailedCount = FailedCount + 1;
                            if( !CancelOrders() )
                            {
                                myLogger.Add(string.Format("CancelOrders fail."));
                                break;
                            }
                        }
                        else // there is opened position - check conditions
                        {
                            decimal diff = 0;
                            decimal tax = GetTaxAmount();
                            tax = tax + tax*0.2m;

                            if ( BaseOrder.BuyOrSell == "1")// sell
                            {                                
                                decimal top = StopOrder.Price;
                                decimal bottom = StopOrder.Price - 2*PipsStep - PipsStep*0.2m;
                                progressPosition = (int)(((top - BuyPrice) / (top - bottom ))*100.0m);

                                decimal d = StopOrder.Price - SellPrice;
                                diff = 2*PipsStep;

                                if (Settings.Settings.SmartStep == "True" && !StopOrderTriggered)
                                    diff = diff * 0.6m;

                                if( d > diff && dPositionResult > (double)tax )
                                {
                                    myLogger.Add(string.Format("LEVEL Reached Buy Price:{0} - reorder stop order.", BuyPrice));
                                    myLogger.Add(string.Format("Current Result: {0} {1}", dResultAll.ToString("F3", CultureInfo.InvariantCulture), Settings.Settings.Instrument.Substring(4, 3)));
                                    if( FailedCount >= 1 )// we exited bad cicle - close position and open new one
                                    {
                                        FailedCount = 0;
                                        obj.ClosePosition(Settings.Settings.Instrument);// cancel opened order
                                        myLogger.Add(string.Format("Opened position closed."));
                                        obj.CancelOrder(StopOrder.ID);
                                        BaseOrder.ID = 0;
                                        StopOrder.ID = 0;
                                        bClosePosition = false;
                                        WriteOrderSettings();
                                    }
                                    else
                                    {
                                        if (Settings.Settings.SmartStep =="True")
                                            myLogger.Add("SMART STEP using!");
                                        InitialLots = (int)dPositionCount/1000;
                                        if (InitialLots < 0)
                                            InitialLots = -1*(int)dPositionCount/1000;
                                        if (!ReorderStopOrder())
                                        {
                                            myLogger.Add(string.Format("CancelOrders fail."));
                                            break;
                                        }
                                    }
                                }
                            }
                            else//buy
                            {

                                decimal bottom = StopOrder.Price;
                                decimal top = StopOrder.Price + 2*PipsStep + PipsStep*0.2m;
                                progressPosition = (int)(((SellPrice-bottom) / (top - bottom))*100.0m);
 
                                decimal d = BuyPrice - StopOrder.Price;

                                diff = 2*PipsStep;

                                if (Settings.Settings.SmartStep =="True" && !StopOrderTriggered )
                                    diff = diff * 0.6m;

                                if( d>diff && dPositionResult>(double)tax )
                                {
                                    myLogger.Add(string.Format("LEVEL Reached Sell Price:{0} - reorder stop order.", SellPrice ) );
                                    myLogger.Add(string.Format("Current Result: {0} {1}", dResultAll.ToString("F3", CultureInfo.InvariantCulture), Settings.Settings.Instrument.Substring(4, 3)));
                                    if (FailedCount >= 1 )// we exited bad cicle - close position and open new one
                                    {
                                        FailedCount = 0;
                                        obj.ClosePosition(Settings.Settings.Instrument);// cancel opened order
                                        myLogger.Add(string.Format("Opened position closed."));                                        
                                        obj.CancelOrder(StopOrder.ID);
                                        BaseOrder.ID = 0;
                                        StopOrder.ID = 0;
                                        bClosePosition = false;
                                        WriteOrderSettings();
                                    }
                                    else
                                    {
                                        if (Settings.Settings.SmartStep =="True")
                                            myLogger.Add("SMART STEP using!");
                                        InitialLots = (int)dPositionCount/1000;
                                        if (InitialLots < 0)
                                            InitialLots = -1*(int)dPositionCount/1000;
                                        if (!ReorderStopOrder())
                                        {
                                            myLogger.Add(string.Format("ReorderStopOrder fail."));
                                            break;
                                        }
                                    }
                                }
                            }
                            
                            if( bClosePosition )
                            {
                                ClosePositionForce();
                                break;                               
                            }
                        }
                    }
                }
                while (true);
            }
            catch (Exception ex)
            {
                myLogger.Add( string.Format("Runtime exception: {0}", ex.Message ) );
            }
            finally
            {
                // Destroy
                errNumber = obj.DestroyClientAPI();
                if (errNumber >= 0)
                    myLogger.Add(string.Format("Cleint API Closed "));
                else
                    myLogger.Add(string.Format("DestroyClientAPI fail. {0}", obj.GetErrDescription(errNumber)));
                myLogger.Add("Job finished.");

            }
        }
    }
}